﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using NEmu;

namespace Super64.Core.Memory.Rom
{
    public static class RomUtility
    {
        public static readonly byte[] Z64_HEADER = {0x80, 0x37, 0x12, 0x40};
        public static readonly byte[] V64_HEADER = { 0x37, 0x80, 0x40, 0x12 };
        public static readonly byte[] N64_HEADER = { 0x40, 0x12, 0x37, 0x80 };
        public const uint CartMaxSize = 0x4000000;

        public static Stream ByteSwapStream(Stream oldStream)
        {
            MemoryStream newSource = new MemoryStream();

            oldStream.Position = 0;

            for (long i = 0; i < oldStream.Length; i+=2)
            {
                ushort word = Tools.ByteSwap(Tools.Create16((byte)oldStream.ReadByte(), (byte)oldStream.ReadByte()));
                newSource.WriteByte((byte)((word & 0xFF00) >> 8));
                newSource.WriteByte((byte)(word & 0xFF));
            }

           return newSource;
        }

        public static Stream WordSwapStream(Stream oldStream)
        {
            MemoryStream newSource = new MemoryStream();

            oldStream.Position = 0;

            for (long i = 0; i < oldStream.Length; i+=4)
            {

                byte b0 = (byte)oldStream.ReadByte(); // [0]
                byte b1 = (byte)oldStream.ReadByte(); // [1]
                byte b2 = (byte)oldStream.ReadByte();  //[2]
                byte b3 = (byte)oldStream.ReadByte();  //[3]
                newSource.WriteByte(b3);
                newSource.WriteByte(b2);
                newSource.WriteByte(b1);
                newSource.WriteByte(b0);
            }

            return newSource;
        }

        public static RomFormat DetectRomFormat(Stream source)
        {
            byte[] header = new byte[4];

            source.Position = 0;

            header[0] = (byte)source.ReadByte();
            header[1] = (byte)source.ReadByte();
            header[2] = (byte)source.ReadByte();
            header[3] = (byte)source.ReadByte();

            if (N64_HEADER.SequenceEqual(header))
                return RomFormat.N64;
            else if (V64_HEADER.SequenceEqual(header))
                return RomFormat.V64;
            else if (Z64_HEADER.SequenceEqual(header))
                return RomFormat.Z64;
            else
                return RomFormat.Unknown;
        }
    }
}
